package com.leslie.hhcommunity.service.impl;

import com.leslie.hhcommunity.entity.User;
import com.leslie.hhcommunity.service.FollowService;
import com.leslie.hhcommunity.service.UserService;
import com.leslie.hhcommunity.util.CommunityConstant;
import com.leslie.hhcommunity.util.RedisKeyUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SessionCallback;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * @author
 * @PackageName:com.leslie.hhcommunity.service.impl
 * @ClassnName:FollowServiceImpl
 * @Description:
 * @Date 2022/1/6  12:00
 */
@Service
public class FollowServiceImpl implements FollowService, CommunityConstant {

	@Autowired
	UserService userService;
	@Autowired
	RedisTemplate redisTemplate;

	/**
	 * 关注
	 *
	 * @param userId 当前登录用户的id
	 * @param entityType 3
	 * @param entityId 被关注者的id
	 */
	@Override
	public void follow(int userId, int entityType, int entityId) {
		redisTemplate.execute(new SessionCallback() {
			@Override
			public Object execute(RedisOperations operations) throws DataAccessException {
				String followeeKey = RedisKeyUtil.getFolloweeKey(userId, entityType);
				String followerKey = RedisKeyUtil.getFollowerKey(entityType, entityId);

				operations.multi();

				//entityId -> 关注的用户的id
				operations.opsForZSet().add(followeeKey, entityId, System.currentTimeMillis());
				//userId -> 当前登录的用户的id
				operations.opsForZSet().add(followerKey, userId, System.currentTimeMillis());

				return operations.exec();
			}
		});
	}

	/**
	 * 取消关注
	 *
	 * @param userId
	 * @param entityType
	 * @param entityId
	 */
	@Override
	public void unfollow(int userId, int entityType, int entityId) {
		redisTemplate.execute(new SessionCallback() {
			@Override
			public Object execute(RedisOperations operations) throws DataAccessException {
				String followeeKey = RedisKeyUtil.getFolloweeKey(userId, entityType);
				String followerKey = RedisKeyUtil.getFollowerKey(entityType, entityId);

				operations.multi();

				operations.opsForZSet().remove(followeeKey, entityId);
				operations.opsForZSet().remove(followerKey, userId);

				return operations.exec();
			}
		});
	}

	/**
	 * 查询用户关注的实体的数量
	 *
	 * @param userId
	 * @param entityType
	 * @return
	 */
	@Override
	public long findFolloweeCount(int userId, int entityType) {
		String followeeKey = RedisKeyUtil.getFolloweeKey(userId, entityType);
		return redisTemplate.opsForZSet().zCard(followeeKey);
	}

	/**
	 * 查询实体粉丝的数量
	 *
	 * @param entityType
	 * @param entityId
	 * @return
	 */
	@Override
	public long findFollowerCount(int entityType, int entityId) {
		String followerKey = RedisKeyUtil.getFollowerKey(entityType, entityId);
		return redisTemplate.opsForZSet().zCard(followerKey);
	}

	/**
	 * 查询当前用户是否关注该实体
	 *
	 * @param userId
	 * @param entityType
	 * @param entityId
	 * @return
	 */
	@Override
	public boolean hasFollowed(int userId, int entityType, int entityId) {
		String followeeKey = RedisKeyUtil.getFolloweeKey(userId, entityType);
		return redisTemplate.opsForZSet().score(followeeKey, entityId) != null;
	}

	/**
	 * 查询某用户关注的人
	 *
	 * @param userId 用户主页的id
	 * @param offset
	 * @param limit
	 * @return
	 */
	@Override
	public List<Map<String, Object>> findFollowees(int userId, int offset, int limit) {
		String followeeKey = RedisKeyUtil.getFolloweeKey(userId, ENTITY_TYPE_USER);
		//某用户关注的人的所有对象的id (value)
		Set<Integer> targetIds = redisTemplate.opsForZSet().reverseRange(followeeKey, offset, offset + limit - 1);
		if (targetIds == null){
			return null;
		}
		List<Map<String,Object>> list = new ArrayList<>();
		for (Integer targetId : targetIds) {
			Map<String,Object> map = new HashMap<>(16);
			User user = userService.findUserById(targetId);
			map.put("user", user);
			Double score = redisTemplate.opsForZSet().score(followeeKey, targetId);
			map.put("followTime", new Date(score.longValue()));
			list.add(map);
		}
		return list;
	}

	/**
	 * 查询某用户的粉丝
	 *
	 * @param userId
	 * @param offset
	 * @param limit
	 * @return
	 */
	@Override
	public List<Map<String, Object>> findFollowers(int userId, int offset, int limit) {
//		String followerKey = RedisKeyUtil.getFollowerKey(userId, ENTITY_TYPE_USER);//这里传反了导致查不到数据
		String followerKey = RedisKeyUtil.getFollowerKey(ENTITY_TYPE_USER, userId);
		Set<Integer> targetIds = redisTemplate.opsForZSet().reverseRange(followerKey, offset, offset + limit - 1);
		if (targetIds == null){
			return null;
		}
		List<Map<String,Object>> list = new ArrayList<>();
		for (Integer targetId : targetIds) {
			Map<String,Object> map = new HashMap<>();
			User user = userService.findUserById(targetId);
			map.put("user", user);
			Double score = redisTemplate.opsForZSet().score(followerKey, targetId);
			map.put("followTime", new Date(score.longValue()));
			list.add(map);
		}
		return list;
	}
}
